<template>
    <div class="search-tree">
        <a-input
          v-model:value = "searchValue"
          :placeholder = "tree.placeholder"
          style = "margin-bottom: 8px;"
          allowClear
          @change = "handleSearch"
        >
            <template #prefix>
                <SearchOutlined />
            </template>
        </a-input>
        <a-tree
            :tree-data = "filteredTreeData"
            :expanded-keys="expandedKeys"
            :selected-keys="selectedKeys"
            :auto-expand-parent = "autoExpandParent"
            @expand = "onExpand"
            @select="onSelect"
        >
            <template #title="{ title }">
                <span v-if="searchValue && title.indexOf(searchValue) > -1">
                    {{ title.substr(0, title.indexOf(searchValue)) }}
                        <span style="color: #f50">{{ searchValue }}</span>
                        {{ title.substr(title.indexOf(searchValue) + searchValue.length) }}
                </span>
                <span v-else>{{ title }}</span>    
            </template>
        </a-tree>
    </div>
</template>

<script lang='ts' setup>
import { TreeProps } from 'ant-design-vue';
import { ref, computed } from 'vue';
import { defineProps } from 'vue';
import { 
    SearchOutlined
} from '@ant-design/icons-vue';

interface TreeNode {
    key: string
    title: string
    children?: TreeNode[]
}

const props = defineProps<{
    tree: any,
    context: any
}>()

const searchValue = ref<string>('')
const expandedKeys = ref<(string | number)[]>(['1'])
const autoExpandParent = ref<boolean>(true)
const selectedKeys = ref<string[]>([])


//过滤树数据
const filteredTreeData = computed(
    () => {
        if(!searchValue.value) return props.tree.treeData;
        return filterTreeData(props.tree.treeData, searchValue.value)
    }
)

//递归过滤树节点
const filterTreeData = (data: TreeNode[], searchVal: string): TreeNode[] =>{
    return data.map(
        (item) => {
            //匹配节点
            const matchTitle = item.title.includes(searchVal);
            //递归树子节点
            let children: TreeNode[] | undefined;
            if(item.children){
                children = filterTreeData(item.children, searchVal)
            }
            //如果符合条件则保留
            if(matchTitle || (children && children.length >0)){
                return {
                    ...item,
                    children
                }
            }
            return null
        }
    ).filter((item): item is TreeNode | any => item !== null)
}

//展开所有包含搜索结果的父节点
const expandMatchedNodes = (data: TreeNode[], searchVal: string, keys: string[] = []) =>{
    data.forEach((item) => {
        if(item.children){
            if(expandMatchedNodes(item.children, searchVal, keys).length || 
            item.title.includes(searchVal)){
                keys.push(item.key)
            }
        }else if(item.title.includes(searchVal)){
            keys.push(item.key)
        }
    })
    return keys
}

//搜索
const handleSearch = () => {
    if(searchValue.value){
        expandedKeys.value = expandMatchedNodes(props.tree.treeData, searchValue.value)
        autoExpandParent.value = true
    }else{
        expandedKeys.value = ['1']
    }
}

//展开节点
const onExpand = (keys: string[]) => {
    expandedKeys.value = keys
    autoExpandParent.value = false
}


//选择节点
const onSelect : TreeProps['onSelect'] = (_selectedKey, info) => {
    props.context.handleSelected(info.selectedNodes[0].title)
}



</script>

<style scoped>
.search-tree{
    padding: 8px;
    background: #fff;
    border-radius: 4px;
}

</style>